home *** CD-ROM | disk | FTP | other *** search
- /*
- Copyright © 1988,1989,1990 by Succinct Systems
-
- 433 Huronview
- Ann Arbor, MI 48103
- (313) 663-4903
-
- File: PixMapFileIO.c
- Model: THINK C 4.0, MPW C 3.0
-
- ABSTRACT:
- PICT file i/o routines, QuickDraw-32 compatible
-
- NOTES:
- saving 32-bit PixMaps requires a lot of temporary heap space for CopyBits
- calls; if your application saves empty (all black) pictures, increase
- the partition size!
-
- KNOWN BUGS:
- The routines which derive pictures from 16 and 32 bit deep PixMaps
- dither them: beauty at the expense of functionality!
-
- HISTORY:
- DAS 08-Jun-89 created this file (David A. Surovell)
- DAS 26-Oct-89 added “rect of interest” control
- DAS 21-Apr-90 cleanly separated PICT <--> PixMap and PICT i/o operations
- added MacPaint B&W file reading
- DAS 27-May-90 added new high-level I/O call discipline
- DAS 08-Jun-90 collected file system arguments into single structure argument
- */
-
- #include <StdMacIncludes.h> /* include standard Mac headers */
- #include <Compatibility.h> /* define compatibility control structures */
- #include "PixMapFileIO.h"
-
-
- OSErr Open_pixel_file(
- PixMapHandle thePixels, /* destination of picture drawing */
- Point *pmBounds, /* returned picture dimensions */
- FSInfoRec *fileSysData ) /* file system info */
- {
- GDHandle savedGDevice;
- SFTypeList theTypeList;
- WindowPtr theDocWindow;
- SFReply userReply;
- Point sfOrigin;
- OSErr errStat;
- long newDirID, procID;
- short newVolRefNum, oldRefNum;
-
- if ((fileSysData == NULL) || (fileSysData == NULL))
- return (OSErr)(-1);
-
- SetPt( &sfOrigin, 80, 30 );
- theTypeList[0] = 'PICT';
- InitCursor();
-
- /* get filename and vRefNum from Standard File dialog box */
- savedGDevice = GetGDevice();
- SetGDevice( GetMainDevice() );
- SFGetFile( sfOrigin, "\p", NULL, 1, theTypeList, NULL, &userReply );
- SetGDevice( savedGDevice );
- if (userReply.good)
- {
- errStat = GetWDInfo(
- userReply.vRefNum, &newVolRefNum, &newDirID, &procID );
-
- if (errStat == noErr)
- {
- SetCursor( *GetCursor( watchCursor ) );
- fileSysData->volumeID = newVolRefNum;
- fileSysData->dirID = newDirID;
- BlockMove(
- &(userReply.fName[0]), fileSysData->fileName,
- (unsigned long)(userReply.fName[0] + 1) );
- errStat = Read_pixel_file( thePixels, pmBounds, fileSysData );
- }
- }
- else
- errStat = abortErr;
-
- InitCursor();
- return errStat;
- }
-
-
- OSErr Read_pixel_file(
- PixMapHandle thePixels, /* destination of picture drawing */
- Point *pmBounds, /* returned picture dimensions */
- FSInfoRec *fileSysData ) /* file system info */
- {
- CGrafPtr aGrafPort;
- CGrafPort aGrafPortStorage;
- GrafPtr savedPort;
- PixMapHandle savedPixels;
- PicHandle thePictHdl;
- Ptr thePictInfo;
- Rect pictFrame;
- OSErr errStat;
- short theFileRefNum;
-
- if ((thePixels == NULL) || (fileSysData == NULL))
- return (OSErr)(-1);
-
- /* read the PICT file */
- errStat = Read_pict_file( &thePictHdl, fileSysData );
-
- /* draw picture onto the PixMap */
- if (errStat == noErr)
- {
- pictFrame = (**thePictHdl).picFrame; /* get picture frame */
- OffsetRect( &pictFrame, -pictFrame.left, -pictFrame.top );
- if (pmBounds != NULL)
- SetPt( pmBounds, pictFrame.right, pictFrame.bottom );
-
- if ((errStat == noErr) && !EmptyRect( &pictFrame ))
- {
- GetPort( &savedPort );
-
- OpenCPort( &aGrafPortStorage );
- aGrafPort = &aGrafPortStorage;
- SetPort( aGrafPort );
- savedPixels = aGrafPort->portPixMap;
- SetPortPix( thePixels );
-
- ClipRect( &((**thePixels).bounds) ); /* open clip to area of PixMap */
-
- DrawPicture( thePictHdl, &pictFrame ); /* draw pict off-screen */
-
- KillPicture( thePictHdl ); /* pitch picture */
- SetPortPix( savedPixels );
- CloseCPort( aGrafPort );
- SetPort( savedPort );
- }
- }
-
- return errStat;
- }
-
-
- /*
- ** save a PixMap as a PICT file, using SFPutFile.
- */
- OSErr Save_pixel_file(
- PixMapHandle thePixels, /* source pixels */
- Rect *rectOfInterest, /* subset of pixmap to save */
- FSInfoRec *fileSysData ) /* file system info */
- {
- GDHandle savedGDevice;
- SFTypeList typeList;
- SFReply userReply;
- Point sfOrigin;
- long newDirID, procID;
- short newVolRefNum;
- OSErr errStat;
-
- if ((thePixels == NULL) || (fileSysData == NULL))
- return (OSErr)(-1);
-
- savedGDevice = GetGDevice();
- SetGDevice( GetMainDevice() );
- SetPt( &sfOrigin, 80, 30 );
- SFPutFile(
- sfOrigin, "\pSave Pixel File As:",
- fileSysData->fileName, NULL, &userReply );
-
- SetGDevice( savedGDevice );
-
- if (userReply.good)
- {
- errStat = GetWDInfo(
- userReply.vRefNum, &newVolRefNum, &newDirID, &procID );
-
- if (errStat == noErr)
- errStat = HCreate(
- newVolRefNum, newDirID, userReply.fName, 'vell', 'PICT' );
-
- if ((errStat == noErr) || (errStat == dupFNErr))
- {
- /* copy fileName and volume refnum */
- fileSysData->volumeID = newVolRefNum;
- fileSysData->dirID = newDirID;
- BlockMove(
- &(userReply.fName[0]), fileSysData->fileName,
- (unsigned long)(userReply.fName[0] + 1) );
-
- errStat = Write_pixel_file(
- thePixels, rectOfInterest, fileSysData );
- }
- }
- else
- errStat = abortErr;
-
- return errStat;
- }
-
-
- /*
- ** write a PixMap out as a PICT file.
- */
- OSErr Write_pixel_file(
- PixMapHandle thePixels, /* source pixels */
- Rect *rectOfInterest, /* subset of pixmap to save */
- FSInfoRec *fileSysData ) /* file system info */
- {
- PicHandle thePictHdl;
- OSErr errStat;
-
- if ((thePixels == NULL) || (fileSysData == NULL))
- return (OSErr)(-1);
-
- SetCursor( *GetCursor( watchCursor ) );
-
- /* create picture, by copying the PixMap onto itself in strips */
- thePictHdl = PixMap_CreatePict( thePixels, rectOfInterest );
- if (thePictHdl == NULL)
- errStat = Write_pict_file( thePictHdl, fileSysData );
- else
- errStat = (OSErr)(-1);
-
- /* finished with PICT, so pitch it */
- if (thePictHdl != NULL)
- KillPicture( thePictHdl );
-
- InitCursor();
-
- return errStat;
- }
-
-
- OSErr Save_GDevice_pixels(
- GDHandle targetGD, /* contains source pixmap to save */
- Rect *rectOfInterest, /* subset of pixmap to save */
- FSInfoRec *fileSysData ) /* file system info */
- {
- GDHandle savedGDevice;
- PicHandle thePictHdl;
- SFReply userReply;
- Point sfOrigin;
- long newDirID, procID;
- short newVolRefNum;
- OSErr errStat = noErr;
-
- if ((targetGD == NULL) || (fileSysData == NULL))
- return (OSErr)(-1);
-
- SetPt( &sfOrigin, 80, 30 );
- savedGDevice = GetGDevice();
-
- SetGDevice( targetGD );
- thePictHdl = PixMap_CreatePict( (**targetGD).gdPMap, rectOfInterest );
- if (thePictHdl == NULL)
- {
- SetGDevice( savedGDevice );
- return (OSErr)(-1);
- }
-
- SetGDevice( GetMainDevice() );
- InitCursor();
- SFPutFile( sfOrigin, "\pSave As…", fileSysData->fileName, NULL, &userReply );
- if (userReply.good)
- {
- errStat =
- GetWDInfo( userReply.vRefNum, &newVolRefNum, &newDirID, &procID );
-
- if (errStat == noErr)
- {
- fileSysData->volumeID = newVolRefNum;
- fileSysData->dirID = newDirID;
- BlockMove(
- userReply.fName, fileSysData->fileName,
- (unsigned long)(userReply.fName[0] + 1) );
-
- errStat = Write_pict_file( thePictHdl, fileSysData );
- }
- }
- else
- errStat = abortErr;
-
- KillPicture( thePictHdl );
- SetGDevice( savedGDevice );
-
- return errStat;
- }
-
-
- OSErr Read_pict_file(
- PicHandle *thePictHdl, /* returned picture, read from file */
- FSInfoRec *fileSysData ) /* file system info */
- {
- Ptr thePictInfo;
- Rect pictFrame;
- OSErr errStat, closeErrStat;
- long pictBytes;
-
- if ((thePictHdl == NULL) || (fileSysData == NULL))
- return (OSErr)(-1);
-
- /* open disk file */
- errStat = HOpen(
- fileSysData->volumeID, fileSysData->dirID,
- fileSysData->fileName, fsRdPerm, &(fileSysData->fileRefNum) );
- if ((fileSysData->fileRefNum < 0) && (errStat == noErr))
- errStat = (OSErr)(-1);
-
- if (errStat == noErr)
- {
- /* find PICT data length, subtracting off the header */
- /* size from the file size itself */
- errStat = GetEOF( fileSysData->fileRefNum, &pictBytes );
- pictBytes -= PICTIO_headersize;
- if (pictBytes <= 0)
- errStat = eofErr;
-
- if (errStat == noErr)
- errStat = SetFPos(
- fileSysData->fileRefNum, fsFromStart, (long)PICTIO_headersize );
-
- /* skip over header */
- if (errStat == noErr)
- {
- *thePictHdl = (PicHandle)NewHandle( pictBytes );
- errStat = MemError();
- }
-
- /* read actual picture data */
- if (errStat == noErr)
- {
- HLock( (Handle)(*thePictHdl) );
- thePictInfo = (Ptr)StripAddress( **thePictHdl );
- errStat = FSRead( fileSysData->fileRefNum, &pictBytes, (Ptr)thePictInfo );
- HUnlock( (Handle)(*thePictHdl) );
- }
-
- if (fileSysData->fileRefNum > 0)
- {
- /* always close the opened file */
- closeErrStat = FSClose( fileSysData->fileRefNum );
- fileSysData->fileRefNum = (-1);
-
- /* preserve any previously reported errors */
- if (errStat == noErr)
- errStat = closeErrStat;
- }
- }
-
- return errStat;
- }
-
-
- OSErr Write_pict_file(
- PicHandle thePictHdl, /* picture to save */
- FSInfoRec *fileSysData ) /* file system info */
- {
- MacDrawFHeader *theFHead;
- Ptr thePictInfo;
- Rect docRect, stripRect;
- OSErr errStat = noErr, closeErrStat;
- long headerBytes, pictBytes;
- short imageWidth, imageHeight;
- short copyStripCount, i;
-
- if ((thePictHdl == NULL) || (fileSysData == NULL))
- return (OSErr)(-1);
- else if (EmptyRect( &((**thePictHdl).picFrame) ))
- return (OSErr)(-1);
-
- pictBytes = GetHandleSize( (Handle)thePictHdl );
- if (pictBytes <= 0L)
- return (OSErr)(-1);
-
- /* create new or open existing disk file */
- errStat = HCreate(
- fileSysData->volumeID, fileSysData->dirID,
- fileSysData->fileName, 'vell', 'PICT' );
- if ((errStat == noErr) || (errStat == dupFNErr))
- errStat = HOpen(
- fileSysData->volumeID, fileSysData->dirID,
- fileSysData->fileName, fsRdWrPerm, &(fileSysData->fileRefNum) );
-
- /* write MacDraw-specific file header */
- if ((errStat == noErr) && (fileSysData->fileRefNum > 0))
- {
- headerBytes = PICTIO_headersize;
- theFHead = (MacDrawFHeader*)NewPtrClear( headerBytes );
- errStat = MemError();
- if (errStat == noErr)
- {
- theFHead->fType = 'DRWG'; /* init MacDraw header info */
- theFHead->hdrID ='MD'; /* ASCII 'MD' for MacDraw */
- theFHead->version = 0;
- }
- else
- theFHead = NULL;
-
- /* write file header */
- if (errStat == noErr)
- errStat = FSWrite( fileSysData->fileRefNum, &headerBytes, theFHead );
-
- /* dispose of file header buffer */
- if (theFHead != NULL)
- DisposPtr( theFHead );
- }
-
- /* write PICT data */
- if (errStat == noErr)
- {
- HLock( thePictHdl );
- thePictInfo = (Ptr)StripAddress( *thePictHdl );
- errStat = FSWrite( fileSysData->fileRefNum, &pictBytes, thePictInfo );
- HUnlock( thePictHdl );
-
- if (errStat == noErr)
- SetEOF( fileSysData->fileRefNum, (long)(pictBytes + headerBytes) );
- }
-
- /* complicated cleanup begins… */
- if (fileSysData->fileRefNum > 0)
- {
- /* always close the opened file, and update volume directory now! */
- closeErrStat = FSClose( fileSysData->fileRefNum );
- fileSysData->fileRefNum = (-1);
- closeErrStat |= FlushVol( NULL, fileSysData->volumeID );
-
- /* preserve any previously reported errors */
- if (errStat == noErr)
- errStat = closeErrStat;
- }
-
- return errStat;
- }
-
-
- OSErr Read_paint_file(
- BitMap *theBits,
- FSInfoRec *fileSysData ) /* file system info */
- {
- GrafPtr savedPort;
- Ptr sourceBuff, sourcePtr, destPtr;
- Ptr thePictInfo;
- OSErr errStat, closeErrStat;
- long paintBytes;
- short i;
-
- if ((theBits == NULL) || (fileSysData == NULL))
- return (OSErr)(-1);
-
- sourceBuff = NewPtr( PAINTIO_blocksize );
- errStat = MemError();
- if (errStat != noErr)
- return errStat;
-
- SetRect( &(theBits->bounds), 0, 0, PAINTIO_width, PAINTIO_height );
- theBits->rowBytes = PAINTIO_rowbytes;
- theBits->baseAddr = NewPtr( PAINTIO_width * PAINTIO_height / 8L );
- errStat = MemError();
- if (errStat != noErr)
- {
- DisposPtr( sourceBuff );
- return errStat;
- }
-
- /* open disk file */
- errStat = HOpen(
- fileSysData->volumeID, fileSysData->dirID,
- fileSysData->fileName, fsRdPerm, &(fileSysData->fileRefNum) );
- if ((fileSysData->fileRefNum < 0) && (errStat == noErr))
- errStat = (OSErr)(-1);
-
- if (errStat == noErr)
- {
- /* find PICT data length, subtracting off the header */
- /* size from the file size itself */
- errStat = GetEOF( fileSysData->fileRefNum, &paintBytes );
- paintBytes -= PICTIO_headersize;
- if (paintBytes <= 0)
- errStat = eofErr;
-
- if (errStat == noErr)
- errStat = SetFPos(
- fileSysData->fileRefNum, fsFromStart, (long)PAINTIO_headersize );
-
- destPtr = theBits->baseAddr;
- for (i=0; (i<PAINTIO_height) && (errStat == noErr); i++)
- {
- /* unpack 72 bytes worth of BitMap pixels */
- sourcePtr = sourceBuff;
- UnpackBits( &sourcePtr, &destPtr, PAINTIO_rowbytes );
-
- /* read the next piece of Paint file into local buffer */
- paintBytes = PAINTIO_blocksize;
- errStat = FSRead( fileSysData->fileRefNum, &paintBytes, sourceBuff );
-
- if ((errStat == eofErr) && (paintBytes >= 0))
- errStat = noErr;
- }
-
- if (fileSysData->fileRefNum > 0)
- {
- /* always close the opened file */
- closeErrStat = FSClose( fileSysData->fileRefNum );
- fileSysData->fileRefNum = (-1);
-
- /* preserve any previously reported errors */
- if (errStat == noErr)
- errStat = closeErrStat;
- }
- }
-
- if (sourceBuff != NULL)
- DisposPtr( sourceBuff );
-
- return errStat;
- }
-
-
- /*
- ** create a QuickDraw picture from a PixMap
- */
- PicHandle PixMap_CreatePict(
- PixMapHandle thePixels,
- Rect *rectOfInterest )
- {
- GrafPtr savedPort;
- CGrafPtr aGrafPort;
- CGrafPort aGrafPortStorage;
- PixMapHandle savedPixels;
- PicHandle newPic;
- OSErr errStat = noErr;
- Rect picRect, stripRect;
- Ptr thePixInfo;
- short copyStripCount, stripHeight, theTransferMode, i;
-
- if (thePixels == NULL)
- return NULL;
- else if ((**thePixels).baseAddr == NULL)
- return NULL;
-
- if (rectOfInterest != NULL)
- picRect = *rectOfInterest;
- else
- {
- picRect = (**thePixels).bounds;
- OffsetRect( &picRect, -picRect.left, -picRect.top );
- }
-
- if (EmptyRect( &picRect ))
- return NULL;
-
- GetPort( &savedPort );
- OpenCPort( &aGrafPortStorage );
- aGrafPort = &aGrafPortStorage;
- SetPort( aGrafPort );
- SetPort( aGrafPort );
- savedPixels = aGrafPort->portPixMap; /* save the current PixMap, to be disposed of later */
- SetPortPix( thePixels ); /* install the target PixMap */
-
- /* keep the size of the copy down to a “reasonable” amount */
- copyStripCount =
- ((long)(picRect.right - picRect.left) * (long)(picRect.bottom - picRect.top))
- / (256L * 64L);
- if ((**thePixels).pixelSize > 8)
- copyStripCount *= 8;
-
- if (copyStripCount < 1)
- copyStripCount = 1;
- else if (copyStripCount > (picRect.bottom - picRect.top))
- copyStripCount = (picRect.bottom - picRect.top);
-
- stripHeight = picRect.bottom / copyStripCount;
- stripRect = picRect;
- stripRect.bottom = stripHeight;
-
- /* optionally dither 32-bit PixMaps */
- theTransferMode = ((**thePixels).pixelSize > 8) ? srcCopy | (short)64 : srcCopy;
-
- HLock( thePixels );
- thePixInfo = (Ptr)StripAddress( *thePixels );
-
- /* clip the drawing sensibly, and copy PixMap onto itself in strips */
- ClipRect( &picRect );
- newPic = OpenPicture( &picRect );
- for (i=0; (i<=copyStripCount) && (errStat == noErr); i++)
- {
- CopyBits(
- thePixInfo, thePixInfo,
- &stripRect, &stripRect, theTransferMode, NULL );
-
- errStat = (OSErr)QDError(); /* check for lack o’ stack! */
-
- OffsetRect( &stripRect, 0, stripHeight );
- if (stripRect.bottom > picRect.bottom)
- stripRect.bottom = picRect.bottom;
- }
- ClosePicture();
-
- HUnlock( thePixels );
-
- /* if QuickDraw reported an error, then the picture it created is */
- /* probably empty, so pitch it */
- if (errStat != noErr)
- {
- KillPicture( newPic );
- newPic = NULL;
- }
-
- SetPortPix( savedPixels ); /* install the original PixMap */
- CloseCPort( aGrafPort ); /* pitch port stuff */
- SetPort( savedPort );
-
- return newPic;
- }
-
-
- void FSInfo_Init(
- FSInfoRec *fileSysData )
- {
- if (fileSysData == NULL)
- RETURN;
-
- fileSysData->dirID = (-1L);
- fileSysData->volumeID = (-1);
- fileSysData->fileRefNum = (-1);
- fileSysData->fileName[0] = '\0';
- }
-
-
- Boolean FSInfo_Valid(
- FSInfoRec *fileSysData )
- {
- if (fileSysData == NULL)
- return FALSE;
-
- return (Boolean)
- ((fileSysData->dirID > 0L) &&
- (fileSysData->volumeID >= 1) &&
- (fileSysData->fileName[0] != '\0'));
- }
-
-
-
-